import { getBaseUrl } from "@/utils/http";

class WebSocketInstance {
  constructor(
    url, callback, 
    onConnect = () => {}, 
    onDisconnect = () => {}, 
    autostart=true
  ) {
    this.connected = false
    this.callback = callback
    this.onConnect = onConnect
    this.onDisconnect = onDisconnect
    this.url = url
    if (autostart) this.initWebsocket()
  }

  initWebsocket = () => {
    // 主动断连标识
    this.toDisconnect = false
    this.ws = new WebSocket(this.url)
    this.ws.onopen = this.onWebsocketOpen
    this.ws.onclose = this.onWebsocketClose
    this.ws.onerror = this.onWebsocketError
    this.ws.onmessage = this.onWebsocketMessage
  }

  reconnect = () => {
    this.toDisconnect = false
    this.__reconnect()
  }

  __reconnect = () => {
    console.log(this.toDisconnect, this.lockReconnect);
    if (this.toDisconnect) return
    if (this.lockReconnect) return
    this.lockReconnect = true
    setTimeout(() => {
      console.log("websocket reconnect...");
      this.initWebsocket();
      this.lockReconnect = false;
    }, 2000);
  }

  send = (req) => {
    if (this.ws.readyState === WebSocket.OPEN) {
      let _msg = req
      if (typeof req !== 'string') _msg = JSON.stringify(req)
      this.ws.send(_msg)
    }
  }
  
  onWebsocketOpen = () => {
    this.connected = true
    this.toDisconnect = false
    this.onConnect()
    console.log("ws open ...")
  }

  onWebsocketError = (e) => {
    this.connected = false
    console.log("ws error: ", e);
    this.__reconnect()
  }

  onWebsocketClose = () => {
    console.log("ws close ...")
    this.onDisconnect()
    if (this.toDisconnect) {
      this.connected = false
    } else {
      this.__reconnect()
    }
  }

  onWebsocketMessage = (res) => {
    const msg = JSON.parse(res.data)
    this.callback(msg)
  }

  close = () => {
    this.toDisconnect = true
    this.ws.close()
  }
}

export const PointRealTime = (callback, onConnect, onDisconnect) => new WebSocketInstance(
  `ws://${getBaseUrl()}point/ws/`, 
  callback, onConnect, onDisconnect
)
export const DeviceRealTime = (callback, onConnect, onDisconnect) => new WebSocketInstance(
  `ws://${getBaseUrl()}device/ws/`, 
  callback, onConnect, onDisconnect
)
export const ScriptRealTime = (callback, onConnect, onDisconnect, autostart) => new WebSocketInstance(
  `ws://${getBaseUrl()}script/ws/`, 
  callback, onConnect, onDisconnect, autostart
)